﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using TangoGames;
using TangoGames.Base;
using TangoGames.Scene;
using incubation_xna3d.HUD;

namespace incubation_xna3d.Scene
{
    public class SceneManager:GameComponent,ISceneManager
    {
        #region Fields

        /// <summary>
        /// camera
        /// </summary>
        ICamera camera;

        /// <summary>
        /// camera control
        /// </summary>
        ICameraControl cameraControl;

        /// <summary>
        /// cenario
        /// </summary>
        IStage stage;

        /// <summary>
        /// Mapa de caminhos
        /// </summary>
        IPathMap pathMap;

        /// <summary>
        /// Contoles do caracter
        /// </summary>
        ICharacter caracter;

        ICharacterControl characterControl;

        List<ICharacter> charactersList = new  List<ICharacter>();

        Dictionary<int, Point> previusPointCharacter;
        
        Dictionary<int, Point> previusPointEnemie;

        /// <summary>
        /// Gerenciador de Inimigos
        /// </summary>
        IEnemiesManager enemiesManager;

        /// <summary>
        /// Gerenciador de Turnos
        /// </summary>
        private ITurnManager turnManager;

        IInputService input;

        #endregion

        #region Properties

        /// <summary>
        /// Camera
        /// </summary>
        public ICamera Camera { get { return camera; } set { camera = value; } }

        /// <summary>
        /// Camera Control
        /// </summary>
        public ICameraControl CameraControl { get { return cameraControl; } set { cameraControl = value; } }

        /// <summary>
        /// Cenario
        /// </summary>
        public IStage Stage { get { return stage; } set { stage = value; } }

        /// <summary>
        /// Mapa de caminhos
        /// </summary>
        public IPathMap PathMap
        {
            get { return pathMap; }
            set
            {
                pathMap = value;
                InitizePathMap();
            }
        }
        /// <summary>
        /// Controle da caracter usado
        /// </summary>
        public ICharacterControl CaracterControl 
        { 
            get { return characterControl; } 
            set 
            { 
                characterControl = value;
                InitializeCharacterControl();
            } 
        }

        /// <summary>
        /// Caracter corrente selecionado
        /// </summary>
        public ICharacter CurrentCharacter { get { return caracter; } set { caracter = value; } }

        /// <summary>
        /// Lista de caracters na scena
        /// </summary>
        public List<ICharacter> CharactersList { get { return charactersList; } set { charactersList = value; } }

        /// <summary>
        /// Gerenciador de inimigos
        /// </summary>
        public IEnemiesManager EnemiesManager 
        { 
            get { return enemiesManager; } 
            set 
            { 
                enemiesManager = value;
                InitializeEnemieManager();
            } 
        }

        /// <summary>
        /// Gerenciador de Turnos
        /// </summary>
        public ITurnManager TurnManager 
        { 
            get { return turnManager; } 
            set 
            { 
                turnManager = value;
                InitializeTurneManager();
            }
        }

        public Hud hudteste { get; set; }


        #endregion

        #region Contructor
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="game"></param>
        public SceneManager(Game game)
            : base(game)
        {
            game.Components.Add(this);

            previusPointCharacter = new Dictionary<int, Point >();

            previusPointEnemie = new Dictionary<int, Point>();

            input = (IInputService)Game.Services.GetService(typeof(IInputService));

        }

        #endregion

        #region Update

        public void UpdatePathMap()
        {
            UpdatePathMap(stage, pathMap);
        }


        public static void UpdatePathMap(IStage stage, IPathMap pathmap)
        {
            foreach (GameObject3D obj in stage.StageModels.Values) 
            {
                pathmap.FlagAsBusy(obj.ModelBoundingBox );
            }
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            UpdateDinamicObjects();

            if ( turnManager.CurrentPlayer == TurnPlayer.HumanPlayer1 &&  input.MouseClick(hudteste.localpassaturno()))
            {
                turnManager.EndPlayerTurn();
            }

        }

        private void UpdateDinamicObjects()
        {
            Point point;

            //Atualiza posição dos personagens
            for (int i=0 ; i < charactersList.Count ;i++)
            {
                
                if (previusPointCharacter.Keys.Contains(i)) 
                {
                    pathMap.ArrayMap[ previusPointCharacter[i].X,previusPointCharacter[i].Y] --;
                }
                point = charactersList[i].BoardPosition;
                pathMap.ArrayMap[point.X, point.Y]++;
                previusPointCharacter[i] = point;
                charactersList[i].UpdateBoardPosition(pathMap);
            }


            ////Atualiza posições do inimigos
            for (int i = 0; i < enemiesManager.EnemiesList.Count; i++)
            {
                if (previusPointEnemie.Keys.Contains(i))
                {
                    pathMap.ArrayMap[previusPointEnemie[i].X, previusPointEnemie[i].Y]--;
                }
                point = enemiesManager.EnemiesList[i].BoardPosition;
                pathMap.ArrayMap[point.X, point.Y]++;
                previusPointEnemie[i] = point;
            }
        }


        #endregion

        #region Methods

        /// <summary>
        /// Adiciona um personagem
        /// </summary>
        /// <param name="character"></param>
        public void AddCharacter(ICharacter character)
        {
            charactersList.Add(character);
            character.SceneManager = this;
        }

        /// <summary>
        /// Inicializa PathMap
        /// </summary>
        private void InitizePathMap()
        {
            pathMap.DiagonalStep = false;
            pathMap.RealisticWay = true;
        }

        /// <summary>
        /// Inicializa EnemieManager
        /// </summary>
        private void InitializeEnemieManager()
        {
            enemiesManager.SceneManager = this;
        }

        /// <summary>
        /// Inicializa contro de caracter
        /// </summary>
        private void InitializeCharacterControl()
        {
            characterControl.SceneManager = this;
        }

        #endregion

        #region TurnControl

        /// <summary>
        /// Inicializa turnos
        /// </summary>
        public void InitializeTurneManager()
        {
            turnManager.PlayersList = new List<TurnPlayer>();
            turnManager.PlayersList.Add(TurnPlayer.HumanPlayer1);
            turnManager.PlayersList.Add(TurnPlayer.AIPlayer1);
            turnManager.TurnElements = new Dictionary<TurnPlayer, List<ITurnElement>>();

            UpdatePlayer1TurnElements();

            UpdateAI1TurnElements();

            turnManager.StartGame();

        }

        private void UpdatePlayer1TurnElements() 
        {
            turnManager.TurnElements[TurnPlayer.HumanPlayer1] = new List<ITurnElement>();
            foreach (ITurnElement elem in Player1Elements) 
            {
                turnManager.TurnElements[TurnPlayer.HumanPlayer1].Add(elem);
            }
        }

        private void UpdateAI1TurnElements()
        {
            turnManager.TurnElements[TurnPlayer.AIPlayer1] = new List<ITurnElement>();
            foreach (ITurnElement elem in AI1Elements)
            {
                turnManager.TurnElements[TurnPlayer.AIPlayer1].Add(elem);
            }
        }


        /// <summary>
        /// Elementos de turno do jogador 1
        /// </summary>
        protected IEnumerable<ITurnElement> Player1Elements
        {
            get
            {
                return from e in charactersList
                       where e is ITurnElement
                       select e as ITurnElement;
            }
        }

        /// <summary>
        /// Elementos de turno do jogador computador
        /// </summary>
        protected IEnumerable<ITurnElement> AI1Elements
        {
            get
            {
                return from e in EnemiesManager.EnemiesList
                       where e is ITurnElement
                       select e as ITurnElement;
            }
        }

        #endregion

    }



}
